﻿#include <Windows.h>
#include "../Memory/memory.hpp"
#include "resource.h"
#include <chrono>
#include <filesystem>
#include <iostream>
#include <string>
#include <thread>
#include <tlhelp32.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include "../ImGui/imgui.h"
#include "../ImGui/imgui_impl_dx11.h"
#include "../ImGui/imgui_impl_win32.h"
#pragma execution_character_set("utf-8")
namespace fs = std::filesystem;
using namespace std;

// 全局变量
Injector inj;
bool g_injectionInProgress = false;
bool g_injectionComplete = false;
bool g_injectionFailed = false;
string g_statusMessage = "等待注入...";
string g_errorMessage = "";
DWORD g_targetPid = 0;

// 函数声明
bool StartCS2Process();
bool ExtractDllToTempPath(string& tempDllPath);
void CleanupTempFiles(const string& tempDllPath);
bool bypass();
DWORD FindCS2Process();
void RenderUI();

// 窗口过程
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// UI样式设置
void SetupImGuiStyle() {
    ImGuiStyle& style = ImGui::GetStyle();
    style.WindowRounding = 5.0f;
    style.FrameRounding = 3.0f;
    style.GrabRounding = 3.0f;
    style.ScrollbarRounding = 5.0f;
}

void InjectionThread() {
    try {
        g_injectionInProgress = true;
        g_statusMessage = "正在启动CS2...";

        // 如果CS2没有运行，则启动它
        if (g_targetPid == 0) {
            if (!StartCS2Process()) {
                g_errorMessage = "无法启动CS2\n请确保Steam和CS2已正确安装";
                g_injectionFailed = true;
                g_injectionInProgress = false;
                return;
            }

            auto startTime = chrono::steady_clock::now();
            DWORD timeoutMs = 60000;
            while (true) {
                g_targetPid = FindCS2Process();
                if (g_targetPid != 0) {
                    break;
                }
                g_statusMessage = "等待CS2启动...";
            }

            if (g_targetPid == 0) {
                g_errorMessage = "无法检测到CS2进程\n请手动启动CS2并重试";
                g_injectionFailed = true;
                g_injectionInProgress = false;
                return;
            }

            // 如果是新启动的CS2，等待7秒
            g_statusMessage = "等待CS2初始化...";
            this_thread::sleep_for(chrono::seconds(10));
        }

        g_statusMessage = "打开CS2进程...";
        inj.process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, g_targetPid);
        if (inj.process == NULL) {
            g_errorMessage = "无法打开CS2进程";
            g_injectionFailed = true;
            g_injectionInProgress = false;
            return;
        }

        g_statusMessage = "定位client.dll...";
        inj.clientDLL = inj.GetModule(g_targetPid, "client.dll");
        if (inj.clientDLL == 0) {
            CloseHandle(inj.process);
            g_errorMessage = "在CS2进程中找不到client.dll";
            g_injectionFailed = true;
            g_injectionInProgress = false;
            return;
        }

        g_statusMessage = "提取DLL到临时位置...";
        string tempDllPath;
        if (!ExtractDllToTempPath(tempDllPath)) {
            CloseHandle(inj.process);
            g_errorMessage = "无法提取DLL到临时位置";
            g_injectionFailed = true;
            g_injectionInProgress = false;
            return;
        }

        g_statusMessage = "绕过VAC检测...";
        if (!bypass()) {
            CleanupTempFiles(tempDllPath);
            CloseHandle(inj.process);
            g_errorMessage = "无法绕过VAC";
            g_injectionFailed = true;
            g_injectionInProgress = false;
            return;
        }
        this_thread::sleep_for(chrono::seconds(1));
        g_statusMessage = "注入DLL...";
        bool injectSuccess = inj.inject(g_targetPid, tempDllPath.c_str());
        if (!injectSuccess) {
            CleanupTempFiles(tempDllPath);
            CloseHandle(inj.process);
            g_errorMessage = "无法注入DLL到CS2进程";
            g_injectionFailed = true;
            g_injectionInProgress = false;
            return;
        }
        this_thread::sleep_for(chrono::seconds(1));
        CleanupTempFiles(tempDllPath);
        CloseHandle(inj.process);

        g_statusMessage = "注入成功!";
        g_injectionComplete = true;
        g_injectionInProgress = false;
        // 获取主窗口句柄的可靠方法
        HWND hMainWindow = FindWindow(NULL, L"SY HEX");
        if (hMainWindow) {
            // 使用 SendMessageTimeout 确保消息被处理
            SendMessageTimeout(hMainWindow, WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG, 1000, NULL);
        }
    }
    catch (const exception& e) {
        g_errorMessage = "发生异常: " + string(e.what());
        g_injectionFailed = true;
        g_injectionInProgress = false;
    }
}

DWORD FindCS2Process() {
    DWORD pid = 0;
    HWND hwnd = FindWindowA(0, "Counter-Strike 2");
    if (hwnd != NULL) {
        GetWindowThreadProcessId(hwnd, &pid);
        if (pid != 0) {
            Injector tempInj;
            DWORD_PTR clientDLL = tempInj.GetModule(pid, "client.dll");
            if (clientDLL != 0) {
                inj.hwndproc = hwnd;
                return pid;
            }
        }
    }
    return 0;
}

bool ExtractDllToTempPath(string& tempDllPath) {
    wchar_t tempPath[MAX_PATH];
    if (GetTempPathW(MAX_PATH, tempPath) == 0) {
        return false;
    }

    wstring tempDir = wstring(tempPath) + L"EZInjector_" + to_wstring(GetTickCount64()) + L"_" + to_wstring(rand());
    if (!CreateDirectoryW(tempDir.c_str(), NULL)) {
        return false;
    }

    wstring tempDllFilePath = tempDir + L"\\sy hex.dll";

    int bufferSize = WideCharToMultiByte(CP_UTF8, 0, tempDllFilePath.c_str(), -1, NULL, 0, NULL, NULL);
    std::string narrowString(bufferSize, 0);
    WideCharToMultiByte(CP_UTF8, 0, tempDllFilePath.c_str(), -1, &narrowString[0], bufferSize, NULL, NULL);
    tempDllPath = narrowString;

    HMODULE hModule = GetModuleHandle(NULL);
    HRSRC hResource = FindResource(hModule, MAKEINTRESOURCE(IDR_DLL_RESOURCE), RT_RCDATA);
    if (hResource == NULL) {
        RemoveDirectoryW(tempDir.c_str());
        return false;
    }

    HGLOBAL hGlobal = LoadResource(hModule, hResource);
    if (hGlobal == NULL) {
        RemoveDirectoryW(tempDir.c_str());
        return false;
    }

    const unsigned char* dllData = static_cast<const unsigned char*>(LockResource(hGlobal));
    if (dllData == NULL) {
        RemoveDirectoryW(tempDir.c_str());
        return false;
    }

    size_t dllSize = SizeofResource(hModule, hResource);
    if (dllSize == 0) {
        RemoveDirectoryW(tempDir.c_str());
        return false;
    }

    FILE* file = NULL;
    if (_wfopen_s(&file, tempDllFilePath.c_str(), L"wb") != 0 || file == NULL) {
        RemoveDirectoryW(tempDir.c_str());
        return false;
    }

    size_t bytesWritten = fwrite(dllData, 1, dllSize, file);
    fclose(file);

    if (bytesWritten != dllSize) {
        DeleteFileW(tempDllFilePath.c_str());
        RemoveDirectoryW(tempDir.c_str());
        return false;
    }

    return true;
}

void CleanupTempFiles(const string& tempDllPath) {
    if (!tempDllPath.empty()) {
        size_t lastSlashPos = tempDllPath.find_last_of("\\/");
        if (lastSlashPos != string::npos) {
            string tempDir = tempDllPath.substr(0, lastSlashPos);

            DeleteFileA(tempDllPath.c_str());
            RemoveDirectoryA(tempDir.c_str());
        }
    }
}

bool StartCS2Process()
{
    wstring steamPath = L"C:\\Program Files (x86)\\Steam\\Steam.exe";
    if (!fs::exists(steamPath)) {
        wchar_t steamInstallPath[MAX_PATH];
        HKEY hKey;
        if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
            DWORD dataSize = sizeof(steamInstallPath);
            if (RegQueryValueExW(hKey, L"SteamPath", NULL, NULL, (LPBYTE)steamInstallPath, &dataSize) == ERROR_SUCCESS) {
                steamPath = wstring(steamInstallPath) + L"\\Steam.exe";
            }
            RegCloseKey(hKey);
        }
    }

    if (!fs::exists(steamPath)) {
        return false;
    }

    wstring commandLine = steamPath + L" -applaunch 730";

    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi;

    if (!CreateProcessW(
        NULL,
        const_cast<LPWSTR>(commandLine.c_str()),
        NULL,
        NULL,
        FALSE,
        0,
        NULL,
        NULL,
        &si,
        &pi
    )) {
        return false;
    }

    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);

    return true;
}

bool bypass()
{
    LPVOID ntOpenFile = GetProcAddress(LoadLibraryW(L"ntdll"), "NtOpenFile");
    if (ntOpenFile) {
        char originalBytes[5];
        memcpy(originalBytes, ntOpenFile, 5);
        WriteProcessMemory(inj.process, ntOpenFile, originalBytes, 5, NULL);
        return true;
    }
    return false;
}

// 窗口过程函数
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
        return true;

    switch (msg) {
    case WM_CLOSE:
        DestroyWindow(hWnd);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE) {
            PostMessage(hWnd, WM_CLOSE, 0, 0);
            return 0;
        }
        break;
    }
    return ::DefWindowProc(hWnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // 初始化随机种子
    srand(static_cast<unsigned int>(time(NULL)));

    // 创建窗口类
    WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
    wc.style = CS_CLASSDC;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpszClassName = L"CS2InjectorWindowClass";
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 0)); // 黑色背景（将被透明覆盖）
    ::RegisterClassEx(&wc);

    // 窗口尺寸
    int windowWidth = 500;
    int windowHeight = 300;

    // 创建窗口（关键修改：使用CreateWindowEx并添加WS_EX_LAYERED）
    HWND hwnd = ::CreateWindowEx(
        WS_EX_LAYERED,
        wc.lpszClassName,
        L"SY HEX",
        WS_POPUP | WS_VISIBLE,
        (GetSystemMetrics(SM_CXSCREEN) - windowWidth) / 2,
        (GetSystemMetrics(SM_CYSCREEN) - windowHeight) / 2,
        windowWidth,
        windowHeight,
        NULL,
        NULL,
        wc.hInstance,
        NULL);

    // 关键修改：设置透明属性必须在窗口显示前
    SetLayeredWindowAttributes(hwnd, 0, 255, LWA_ALPHA);

    // 修改Direct3D初始化
    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd, sizeof(sd));
    sd.BufferCount = 2;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // 必须使用带alpha的格式
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = hwnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;
    sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;


    UINT createDeviceFlags = 0;
    D3D_FEATURE_LEVEL featureLevel;
    const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
    ID3D11Device* pd3dDevice = nullptr;
    ID3D11DeviceContext* pd3dDeviceContext = nullptr;
    IDXGISwapChain* pSwapChain = nullptr;

    if (FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &pSwapChain, &pd3dDevice, &featureLevel, &pd3dDeviceContext))) {
        MessageBoxA(NULL, "Failed to create D3D11 device and swap chain", "Error", MB_ICONERROR);
        return 1;
    }

    // 创建渲染目标视图
    ID3D11Texture2D* pBackBuffer;
    pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
    ID3D11RenderTargetView* mainRenderTargetView;
    pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &mainRenderTargetView);
    pBackBuffer->Release();

    // 初始化ImGui
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    io.IniFilename = nullptr;
    // 关键修改：完全透明的样式设置
    ImGuiStyle& style = ImGui::GetStyle();
    style.WindowRounding = 10.0f;
    style.Colors[ImGuiCol_WindowBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
    style.Colors[ImGuiCol_Border] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
    style.Colors[ImGuiCol_FrameBg] = ImVec4(0.2f, 0.2f, 0.2f, 0.5f);
    style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.3f, 0.3f, 0.3f, 0.5f);
    style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.4f, 0.4f, 0.4f, 0.5f);
    SetupImGuiStyle();

    // 尝试加载字体，如果失败则使用默认字体
    ImFont* font = nullptr;
    try {
        ImFontConfig font_cfg;
        font_cfg.FontDataOwnedByAtlas = false;
        font = io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\msyhbd.ttc", 24.0f, &font_cfg, io.Fonts->GetGlyphRangesChineseFull());
    }
    catch (...) {
        font = io.Fonts->AddFontDefault();
    }

    ImGui_ImplWin32_Init(hwnd);
    ImGui_ImplDX11_Init(pd3dDevice, pd3dDeviceContext);

    // 显示窗口
    ::ShowWindow(hwnd, SW_SHOWDEFAULT);
    ::UpdateWindow(hwnd);

    // 主循环
    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != WM_QUIT) {
        if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
            continue;
        }

        // 开始ImGui帧
        ImGui_ImplDX11_NewFrame();
        ImGui_ImplWin32_NewFrame();
        ImGui::NewFrame();

        // 渲染UI
        RenderUI();

        // 渲染 - 使用透明背景
        ImGui::Render();
        const float clear_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
        pd3dDeviceContext->OMSetRenderTargets(1, &mainRenderTargetView, nullptr);
        pd3dDeviceContext->ClearRenderTargetView(mainRenderTargetView, clear_color);
        ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

        pSwapChain->Present(1, 0);
    }

    // 清理
    ImGui_ImplDX11_Shutdown();
    ImGui_ImplWin32_Shutdown();
    ImGui::DestroyContext();

    if (pSwapChain) pSwapChain->Release();
    if (mainRenderTargetView) mainRenderTargetView->Release();
    if (pd3dDevice) pd3dDevice->Release();
    if (pd3dDeviceContext) pd3dDeviceContext->Release();

    ::DestroyWindow(hwnd);
    ::UnregisterClass(wc.lpszClassName, wc.hInstance);

    return 0;
}
// 在全局变量区域添加
static bool g_injectionStarted = false;

void RenderUI() {
    // 设置窗口样式
    ImGuiStyle& style = ImGui::GetStyle();
    style.WindowRounding = 10.0f;
    style.Colors[ImGuiCol_WindowBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);

    ImGui::SetNextWindowPos(ImVec2(0, 0));
    ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize);

    // 开始主窗口
    ImGui::Begin("##Screen", nullptr,
        ImGuiWindowFlags_NoCollapse |
        ImGuiWindowFlags_NoResize |
        ImGuiWindowFlags_NoTitleBar |
        ImGuiWindowFlags_NoScrollbar |
        ImGuiWindowFlags_NoScrollWithMouse |
        ImGuiWindowFlags_NoBackground);

    // 手动绘制半透明背景
    ImDrawList* draw = ImGui::GetWindowDrawList();
    ImVec2 windowPos = ImGui::GetWindowPos();
    ImVec2 windowSize = ImGui::GetWindowSize();

    // 绘制半透明背景
    draw->AddRectFilled(
        windowPos,
        ImVec2(windowPos.x + windowSize.x, windowPos.y + windowSize.y),
        IM_COL32(20, 20, 20, 200),
        5.0f,
        ImDrawFlags_RoundCornersAll
    );

    // 先绘制标题文字
    ImGui::SetCursorPos(ImVec2(10, 5));
    ImGui::TextColored(ImVec4(0.0f, 0.7f, 1.0f, 1.0f), "SY HEX");

    // 关闭按钮
    ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 80, 5));
    ImGui::PushFont(ImGui::GetFont());
    ImGui::SetWindowFontScale(0.7f);

    if (g_injectionStarted) {
        ImGui::BeginDisabled(); // 禁用按钮
    }

    if (ImGui::Button("关闭", ImVec2(70, 25))) {
        PostMessage(GetActiveWindow(), WM_CLOSE, 0, 0);
    }
    if (g_injectionStarted) {
        ImGui::EndDisabled(); // 结束禁用
    }

    ImGui::SetWindowFontScale(1.0f);
    ImGui::PopFont();

    // 创建透明的可拖动区域（避开关闭按钮区域）
    ImGui::SetCursorPos(ImVec2(0, 0));
    ImGui::InvisibleButton("##DragArea", ImVec2(ImGui::GetWindowWidth() - 80, 30));

    // 拖动逻辑
    static POINT s_dragStartPos;
    static POINT s_windowStartPos;
    static bool s_isDragging = false;

    if (ImGui::IsItemActive()) {
        if (ImGui::IsMouseClicked(0)) {
            GetCursorPos(&s_dragStartPos);
            RECT windowRect;
            GetWindowRect(GetActiveWindow(), &windowRect);
            s_windowStartPos.x = windowRect.left;
            s_windowStartPos.y = windowRect.top;
            s_isDragging = true;
        }
        else if (ImGui::IsMouseDragging(0) && s_isDragging) {
            POINT currentMousePos;
            GetCursorPos(&currentMousePos);

            int newX = s_windowStartPos.x + (currentMousePos.x - s_dragStartPos.x);
            int newY = s_windowStartPos.y + (currentMousePos.y - s_dragStartPos.y);

            SetWindowPos(GetActiveWindow(), NULL, newX, newY, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
        }
    }
    else {
        s_isDragging = false;
    }

    ImGui::Separator();
    ImGui::Spacing();

    // 状态信息
    ImGui::Text("状态: ");
    ImGui::SameLine();

    if (g_injectionInProgress) {
        ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), g_statusMessage.c_str());
    }
    else if (g_injectionComplete) {
        ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), g_statusMessage.c_str());
    }
    else if (g_injectionFailed) {
        ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), g_statusMessage.c_str());
    }
    else {
        ImGui::Text(g_statusMessage.c_str());
    }

    // 错误信息
    if (!g_errorMessage.empty()) {
        ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "错误: %s", g_errorMessage.c_str());
    }

    // 显示CS2进程信息
    if (g_targetPid != 0) {
        ImGui::Spacing();
        ImGui::Separator();
        ImGui::Spacing();
        ImGui::Text("CS2进程ID: %d", g_targetPid);
    }

    // 注入按钮
    ImGui::SetCursorPosX((ImGui::GetWindowSize().x - 150) * 0.5f);
    ImGui::SetCursorPosY(250.f);
    if (g_injectionStarted) {
        ImGui::BeginDisabled();
    }
    if (ImGui::Button("注入", ImVec2(150, 40))) {
        if (!g_injectionInProgress && !g_injectionComplete) {
            g_targetPid = FindCS2Process();
            g_injectionStarted = true; // 设置注入已开始标志
            thread injectThread(InjectionThread);
            injectThread.detach();
        }
    }
    if (g_injectionStarted) {
        ImGui::EndDisabled();
    }

    ImGui::End();
}